{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# import \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import unittest"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "数据文件已经是处理好的单词，每封邮件一行"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 贝叶斯"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.7368421052631579"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#先验概率： \n",
    "# 好样本： \n",
    "1400/(1400+500)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.2631578947368421"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 坏样本： \n",
    "500/(1400+500)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# src"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "test_classify (__main__.TestEmailClassifier) ... ok\n",
      "test_get_files_form_dir (__main__.TestEmailClassifier) ... ok\n",
      "test_get_words_from_file (__main__.TestEmailClassifier) ... ok\n",
      "test_judge (__main__.TestEmailClassifier) ... ok\n",
      "test_score (__main__.TestEmailClassifier) ... ok\n",
      "test_train (__main__.TestEmailClassifier) ... ok\n",
      "\n",
      "----------------------------------------------------------------------\n",
      "Ran 6 tests in 0.012s\n",
      "\n",
      "OK\n"
     ]
    }
   ],
   "source": [
    "#tdd\n",
    "import unittest\n",
    "\n",
    "# 待编写\n",
    "#from email_classifier import EmailClassifier\n",
    "class TestEmailClassifier(unittest.TestCase):\n",
    "    def setUp(self):\n",
    "        # notin book please PLEASE\n",
    "        self.tmp_file = '../data/tmp/tmp.txt'\n",
    "\n",
    "        #self.spam_dir='../data/processed/spam_500/'\n",
    "        #self.ham_dir='../data/processed/ham_1400/'\n",
    "\n",
    "        # spam buy buy this book http www\n",
    "        self.spam_dir = '../data/test_spam/'\n",
    "        # 1:ham this is ham please refer this book\n",
    "        # 2:ham please refer this book\n",
    "        self.ham_dir = '../data/test_ham/'\n",
    "\n",
    "        self.clf = EmailClassifier(self.spam_dir, self.ham_dir)\n",
    "\n",
    "    def test_get_files_form_dir(self):\n",
    "        a_bad = EmailClassifier.get_files_form_dir(self.spam_dir)\n",
    "        a_good = EmailClassifier.get_files_form_dir(self.ham_dir)\n",
    "        self.assertEqual(len(a_bad), 1)\n",
    "        self.assertEqual(len(a_good), 2)\n",
    "\n",
    "    # 测试文本解析功能:全部小写，取集合\n",
    "    # expectation : e ;a = actual\n",
    "    def test_get_words_from_file(self):\n",
    "        e = set(['notin', 'book', 'please'])\n",
    "        a = EmailClassifier.get_words_from_file(self.tmp_file)\n",
    "        self.assertSetEqual(a, e)\n",
    "\n",
    "    def test_train(self):\n",
    "        #clf = EmailClassifier(self.spam_dir, self.ham_dir)\n",
    "        self.clf.train()\n",
    "        self.assertEqual(self.clf.total_count['spam'], 6)\n",
    "        self.assertEqual(self.clf.total_count['ham'], 11)\n",
    "        self.assertEqual(self.clf.training['ham']['please'], 2)\n",
    "        self.assertEqual(self.clf.training['spam']['buy'], 1)\n",
    "\n",
    "    def test_score(self):\n",
    "        \n",
    "        def _format_dict(d):\n",
    "            return {k: round(v, 3) for k, v in d.items()}\n",
    "            \n",
    "        a = {\n",
    "            'ham': round(2 / 3 * 1 / 12 * 3 / 12 * 3 / 12, 7),#7。0.003472222222222222\n",
    "            'spam': round(1 / 3 * 1 / 7 * 2 / 7 * 1 / 7, 7)# 7\n",
    "        }\n",
    "        a = {\n",
    "            'ham':(2 / 3) * (1 / 12) * (3 / 12) * (3 / 12)*(1000**3), #0.003472222222222222\n",
    "            'spam': (1 / 3) * (1 / 7) * (2 / 7 )*( 1 / 7) *(1000**3)\n",
    "        }\n",
    "        #clf = EmailClassifier(self.spam_dir, self.ham_dir) \n",
    "        self.clf.train()\n",
    "        e = self.clf.score(self.tmp_file)\n",
    "        # 原来的\n",
    "        # self.assertDictEqual(a, e)\n",
    "        self.assertDictEqual(_format_dict(a), _format_dict(e))\n",
    "        \n",
    "        \n",
    "\n",
    "    def test_judge(self):\n",
    "        #self.clf.train()\n",
    "        t = self.clf.score(self.tmp_file)\n",
    "        e = {'ham':0.0034722}# 原始测试\n",
    "        e = {'ham':3472222.2222222215}# 真实调整\n",
    "        a = self.clf.judge(t)\n",
    "        self.assertDictEqual(a, e)\n",
    "        \n",
    "    def test_classify(self):\n",
    "        #t = self.clf.score(self.tmp_file)\n",
    "        #e = {'ham':0.0034722}\n",
    "        e = {'ham':3472222.2222222215}# 真实调整\n",
    "        #a = self.clf.judge(t)\n",
    "        a = self.clf.classify(self.tmp_file)\n",
    "        self.assertDictEqual(a, e)\n",
    "        \n",
    "        \n",
    "if __name__ == '__main__':\n",
    "    # 方式一：python -m unittest exame_test\n",
    "    #unittest.main()\n",
    "\n",
    "    # 方式二\n",
    "    # 构造测试集\n",
    "    #suite = unittest.TestSuite()\n",
    "    #suite.addTest(TestEmailClassifier('test_get_words_from_file'))\n",
    "    ## 执行测试\n",
    "    #runner = unittest.TextTestRunner()\n",
    "    #runner.run(suite)\n",
    "\n",
    "    # 方式三\n",
    "    suite = unittest.defaultTestLoader.loadTestsFromTestCase(\n",
    "        TestEmailClassifier)\n",
    "    unittest.TextTestRunner(verbosity=2).run(suite)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 292,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.003472222222222222"
      ]
     },
     "execution_count": 292,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "2 / 3 * 1 / 12 * 3 / 12 * 3 / 12"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 290,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.003472222"
      ]
     },
     "execution_count": 290,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "round(2 / 3 * 1 / 12 * 3 / 12 * 3 / 12, 9)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 运行"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "凡是以test开头的方法都是测试方法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "import re\n",
    "import io\n",
    "import os\n",
    "import glob\n",
    "from collections import defaultdict\n",
    "\n",
    "\n",
    "class EmailClassifier:\n",
    "    '''\n",
    "    spam:垃圾邮件\n",
    "    ham: 正常邮件\n",
    "    '''\n",
    "    def __init__(self, spam_dir, ham_dir):\n",
    "        self.CAT = ['ham', 'spam']\n",
    "        self.spam_list = EmailClassifier.get_files_form_dir(spam_dir)\n",
    "        self.ham_list = EmailClassifier.get_files_form_dir(ham_dir)\n",
    "        # 先验\n",
    "        p_ham = len(self.ham_list) / (len(self.ham_list) + len(self.spam_list))\n",
    "        self.P = {self.CAT[0]: p_ham, self.CAT[1]: 1 - p_ham}\n",
    "\n",
    "        # 记录每个类别下每个单词的计数\n",
    "        self.training = {c: defaultdict(float) for c in self.CAT}\n",
    "        # 记录每个类别单词总数\n",
    "        self.total_count = {self.CAT[0]: 0, self.CAT[1]: 0}\n",
    "        # 可当做超参数\n",
    "        self.super_m = 1000\n",
    "\n",
    "    @staticmethod\n",
    "    def get_words_from_file(file):\n",
    "        with io.open(file, 'r') as f:\n",
    "            c = re.findall('\\w+', f.read().lower())\n",
    "        return set(c)\n",
    "\n",
    "    @staticmethod\n",
    "    def get_files_form_dir(path):\n",
    "        return glob.glob(os.path.join(path, '*.*'))\n",
    "\n",
    "    def train(self):\n",
    "        # 单词统计\n",
    "        for t in zip(self.CAT, [self.ham_list, self.spam_list]):\n",
    "            for s in t[1]:\n",
    "                words = EmailClassifier.get_words_from_file(s)\n",
    "                self.total_count[t[0]] += len(words)\n",
    "                for ww in words:\n",
    "                    self.training[t[0]][ww] += 1\n",
    "\n",
    "    def score(self, email_file):\n",
    "        if self.total_count[self.CAT[0]] == 0 or self.total_count[\n",
    "                self.CAT[1]] == 0:\n",
    "            self.train()\n",
    "        result = self.P.copy()\n",
    "        for ww in EmailClassifier.get_words_from_file(email_file):\n",
    "            for cc in self.CAT:\n",
    "                v = self.training[cc][ww]\n",
    "                # 乘以 1000，避免数值太小\n",
    "                #p = (v + 1) / (self.total_count[cc] + 1)\n",
    "                p = self.super_m*(v + 1) / (self.total_count[cc] + 1)\n",
    "                #p = (1000*v + 1) / (self.total_count[cc] + 1)\n",
    "                result[cc] *= p\n",
    "        \n",
    "        return result\n",
    "        # 返回7位小数\n",
    "        return {k: round(v, 7) for k, v in result.items()}\n",
    "\n",
    "    #@staticmethod\n",
    "    def judge(self,score_dict):\n",
    "        '''二分类'''\n",
    "        keys = self.CAT #list(score_dict.keys())\n",
    "        if score_dict[keys[0]] >= score_dict[keys[1]]:\n",
    "            return {keys[0]: score_dict[keys[0]]}\n",
    "        else:\n",
    "            return {keys[1]: score_dict[keys[1]]}\n",
    "\n",
    "    def classify(self, email_file):\n",
    "        score = self.score(email_file)\n",
    "        return self.judge(score)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 验证集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "s = '../data/processed/spam_400/'\n",
    "h = '../data/processed/ham_1120/'\n",
    "clf = EmailClassifier(s, h)\n",
    "clf.train()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'ham': 165655, 'spam': 71005}"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "clf.total_count"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "312.0"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "clf.training['spam']['you']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'spam': 1.8387229565810378e-153}\n",
      "{'spam': 2.029211278197064e-148}\n",
      "{'ham': 0.0}\n",
      "{'ham': 6.23380504773489e-64}\n",
      "{'ham': 0.0}\n",
      "{'ham': 0.0}\n",
      "{'ham': 0.0}\n",
      "accuracy:0.9815789473684211\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(95, 5, 278, 2)"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 整体*1000 ： （95, 5, 278, 2)\n",
    "# 分开1000： (93, 7, 280, 0)\n",
    "predict(clf,v_h,v_s)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "def predict(clf, ham_dir, spam_dir):\n",
    "    ham_list = EmailClassifier.get_files_form_dir(ham_dir)\n",
    "    spam_list = EmailClassifier.get_files_form_dir(spam_dir)\n",
    "    tp,fp,tn,fn = 0,0,0,0\n",
    "\n",
    "    for hh in ham_list:\n",
    "        t = clf.classify(hh)\n",
    "        if 'ham' in t:\n",
    "            #print(t)\n",
    "            tn += 1\n",
    "        else:\n",
    "            print(t)\n",
    "            fn += 1\n",
    "            \n",
    "    for ss in spam_list:\n",
    "        t = clf.classify(ss)\n",
    "        if 'spam' in t:\n",
    "            tp += 1\n",
    "        else:\n",
    "            print(t)\n",
    "            fp += 1\n",
    "    \n",
    "    accuracy = (tp + tn) / (tp+tn+fp+fn)\n",
    "    print('accuracy:{}'.format(accuracy))\n",
    "    return tp,fp,tn,fn\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "v_s = '../data/validate/spam/'\n",
    "v_h = '../data/validate/ham/'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 209,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0, 400, 1120, 0)"
      ]
     },
     "execution_count": 209,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "predict(clf,h,s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# doc"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## unittest\n",
    "\n",
    "https://docs.python.org/3/library/unittest.html"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 常用测试断言\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "ename": "AssertionError",
     "evalue": "断言失败",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m\u001b[0m",
      "\u001b[0;31mAssertionError\u001b[0mTraceback (most recent call last)",
      "\u001b[0;32m<ipython-input-4-814d6d5d4efd>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32massert\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m==\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'断言失败'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mAssertionError\u001b[0m: 断言失败"
     ]
    }
   ],
   "source": [
    "assert 1==2,'断言失败'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "t_test = unittest.TestCase()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "ename": "AssertionError",
     "evalue": "1 != 2 : 断言失败",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m\u001b[0m",
      "\u001b[0;31mAssertionError\u001b[0mTraceback (most recent call last)",
      "\u001b[0;32m<ipython-input-6-4c4d7329abd9>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;31m# 基本使用方法\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mt_test\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0massertEqual\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'断言失败'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m/usr/lib/python3.6/unittest/case.py\u001b[0m in \u001b[0;36massertEqual\u001b[0;34m(self, first, second, msg)\u001b[0m\n\u001b[1;32m    827\u001b[0m         \"\"\"\n\u001b[1;32m    828\u001b[0m         \u001b[0massertion_func\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_getAssertEqualityFunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfirst\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msecond\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 829\u001b[0;31m         \u001b[0massertion_func\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfirst\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msecond\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmsg\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    830\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    831\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0massertNotEqual\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfirst\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msecond\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmsg\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;32m/usr/lib/python3.6/unittest/case.py\u001b[0m in \u001b[0;36m_baseAssertEqual\u001b[0;34m(self, first, second, msg)\u001b[0m\n\u001b[1;32m    820\u001b[0m             \u001b[0mstandardMsg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'%s != %s'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0m_common_shorten_repr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfirst\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msecond\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    821\u001b[0m             \u001b[0mmsg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_formatMessage\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstandardMsg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 822\u001b[0;31m             \u001b[0;32mraise\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfailureException\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    823\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    824\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0massertEqual\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfirst\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msecond\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmsg\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mAssertionError\u001b[0m: 1 != 2 : 断言失败"
     ]
    }
   ],
   "source": [
    "# 基本使用方法\n",
    "t_test.assertEqual(1,2,'断言失败')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "t_test.assertCountEqual([1,2,3,1],[3,2,1,1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "ename": "AssertionError",
     "evalue": "Regex didn't match: '\\\\d' not found in 'abc' : 失败",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m\u001b[0m",
      "\u001b[0;31mAssertionError\u001b[0mTraceback (most recent call last)",
      "\u001b[0;32m<ipython-input-8-d4c7094befd7>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;31m#search(r\"(\\w)+\", \"abc\")\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0mt_test\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0massertRegex\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'abc'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'(\\w)+'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mt_test\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0massertRegex\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'abc'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'\\d'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'失败'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m/usr/lib/python3.6/unittest/case.py\u001b[0m in \u001b[0;36massertRegex\u001b[0;34m(self, text, expected_regex, msg)\u001b[0m\n\u001b[1;32m   1297\u001b[0m             \u001b[0;31m# _formatMessage ensures the longMessage option is respected\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1298\u001b[0m             \u001b[0mmsg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_formatMessage\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstandardMsg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1299\u001b[0;31m             \u001b[0;32mraise\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfailureException\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m   1300\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m   1301\u001b[0m     \u001b[0;32mdef\u001b[0m \u001b[0massertNotRegex\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtext\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0munexpected_regex\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmsg\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
      "\u001b[0;31mAssertionError\u001b[0m: Regex didn't match: '\\\\d' not found in 'abc' : 失败"
     ]
    }
   ],
   "source": [
    "#search(r\"(\\w)+\", \"abc\")\n",
    "t_test.assertRegex('abc', '(\\w)+')\n",
    "t_test.assertRegex('abc', '\\d','失败')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# end"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "255.188px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
